/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package aeronef;

import aeronef.appStates.GameState;
import aeronef.builder.AbstractBuilder;
import aeronef.builder.ShipBuilder;
import aeronef.model.Ship;
import aeronef.model.Scenario;
import com.jme3.asset.AssetManager;
import com.jme3.asset.TextureKey;
import com.jme3.bullet.control.RigidBodyControl;
import com.jme3.math.FastMath;
import com.jme3.math.Plane;
import com.jme3.math.Quaternion;
import com.jme3.math.Vector2f;
import com.jme3.math.Vector3f;
import com.jme3.renderer.queue.RenderQueue.ShadowMode;
import com.jme3.scene.Geometry;
import com.jme3.scene.Node;
import com.jme3.scene.Spatial.CullHint;
import com.jme3.scene.shape.Quad;
import com.jme3.texture.Texture;
import com.jme3.util.SkyFactory;
import com.jme3.water.SimpleWaterProcessor;
import org.w3c.dom.Element;

/**
 *
 * @author Hagan
 */
public class ScenarioManager extends AbstractBuilder {
    
    protected Node rootNode;
    protected Scenario scenario;
    
 
    public ScenarioManager(GameState gameState) {
        super(gameState);
        this.rootNode = gameState.getRootNode();
    }
    
    public void buildScenario(String scenarioName) {
        
        String definitionString = (String) assetManager.loadAsset("Data/scenarios/" + scenarioName + ".xml");
        definition = buildDocument(definitionString);
        buildEnvironment();
        placeShips();
    }
    
    private void buildEnvironment() {
        String skybox = getTagValue("skybox", definition.getDocumentElement());
        buildSkybox(skybox);
        buildOcean();
    }
    
    private void buildSkybox(String name) {
        rootNode.setCullHint( CullHint.Never );
        String path = "Textures/envmaps/" + name + "/" + name + "_";
        rootNode.attachChild(SkyFactory.createSky(assetManager, 
                texture(path+"ft.png"), texture(path+"bk.png"),
                texture(path+"lf.png"), texture(path+"rt.png"),
                texture(path + "up.png"), texture(path + "dn.png")));
    }

    private Texture texture(String textureName) {
        TextureKey key = new TextureKey(textureName, true);
        key.setGenerateMips(true);
        return assetManager.loadTexture(key);
    }

    private void buildOcean() {
        SimpleWaterProcessor waterProcessor = new SimpleWaterProcessor(assetManager);
        waterProcessor.setReflectionScene(rootNode);

        // we set the water plane
        Vector3f waterLocation = new Vector3f(0, 0, 0);
        waterProcessor.setPlane(new Plane(Vector3f.UNIT_Y, waterLocation.dot(Vector3f.UNIT_Y)));
        gameState.getViewPort().addProcessor(waterProcessor);

        // we set wave properties
        waterProcessor.setWaterDepth(40);         // transparency of water
        waterProcessor.setDistortionScale(0.10f); // strength of waves
        waterProcessor.setWaveSpeed(0.01f);       // speed of waves
        waterProcessor.setRenderSize(128,128);
        
        // we define the wave size by setting the size of the texture coordinates
        Quad quad = new Quad(1024, 1024);
        quad.scaleTextureCoordinates(new Vector2f(60f, 60f));

        // we create the water geometry from the quad
        Geometry water = new Geometry("water", quad);
        water.setLocalRotation(new Quaternion().fromAngleAxis(-FastMath.HALF_PI, Vector3f.UNIT_X));
        water.setLocalTranslation(-512, 0, 512);
        water.setShadowMode(ShadowMode.Receive);
        water.setMaterial(waterProcessor.getMaterial());
        rootNode.attachChild(water);
    }

    private void placeShips() {
        
        // later, this will be controller by a scenario file.  For now, load one ship.
        ShipBuilder shipBuilder = new ShipBuilder(gameState);
        for (Element batteryElement : getElementsByTagName(definition.getDocumentElement(), "ship")) {
            
            String type = getTagValue("type", batteryElement);
            String name = getTagValue("name", batteryElement);
            Ship aeronef = shipBuilder.buildFromDefinition(name, type);
            
            Float xPos = getTagValueAsFloat("xPos", batteryElement);
            Float yPos = getTagValueAsFloat("yPos", batteryElement);
            Float zPos = getTagValueAsFloat("zPos", batteryElement);
            
            rootNode.attachChild(aeronef);
            RigidBodyControl control = aeronef.getControl(RigidBodyControl.class);
            control.setPhysicsLocation(new Vector3f(xPos, yPos, zPos));
            
            gameState.getNefs().add(aeronef);
            gameState.setPlayerNef(aeronef);
        }
    }
    
    
}
